package com.putao.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.putao.base.BaseService;
import com.putao.base.BaseWrapper;
import com.putao.constants.Constants;
import com.putao.domain.Account;
import com.putao.domain.Bill;
import com.putao.error.BusinessException;
import com.putao.mapper.AccountMapper;
import com.putao.service.AccountService;
import com.putao.service.BillService;
import com.putao.utils.AssertUtil;
import com.putao.utils.StringUtils;
import com.putao.vo.AccountVo;
import com.putao.vo.BaseVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.putao.enums.SystemCodeEnum.ACCOUNT_NAME_FORMAT_ERROR;

/**
 * @author fuhehuang
 * @email 2628279194@qq.com
 */
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements AccountService, BaseService<Account> {

    @Autowired
    private BillService billService;

    @Override
    public Account saveAccount(AccountVo accountVO) {
        Account account = new Account();
        BeanUtils.copyProperties(accountVO, account);
        account.insertInit();
        account.setTotalNum(BigDecimal.ZERO);
        // 设置计算balance的钱
        account.initBalance();
        if (accountVO.getLastFourDigitsOfCard().length() > 4) {
            throw new BusinessException("尾号不能超过4位，请重新输入");
        }
        this.check(account, null);
        this.save(account);
        return account;
    }

    @Override
    public List<AccountVo> selectListByPhone(BaseVo baseVo, String userId, QueryWrapper<Account> wrapper) {
        wrapper.orderByDesc("create_time");
        List<Account> accountList = this.list(wrapper);
        if (CollectionUtil.isEmpty(accountList)) {
            return new ArrayList<>();
        }
        List<Bill> billList = billService.list(new BaseWrapper<Bill>().init(userId));
        Map<String, List<Bill>> accountIdBillListMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(billList)) {
            accountIdBillListMap = billList.stream().collect(Collectors.groupingBy(Bill::getAccountId));
        }
        List<AccountVo> accountVoList = new ArrayList<>();
        for (Account account : accountList) {
            AccountVo accountVo = new AccountVo();
            BeanUtils.copyProperties(account, accountVo);
            accountVo.setBillList(accountIdBillListMap.get(account.getId()));
            accountVoList.add(accountVo);
        }
        return accountVoList;
    }

    @Override
    public void updateAccount(AccountVo accountVo) {
        Account account = new Account();
        BeanUtils.copyProperties(accountVo, account);
        account.updateInit();
        // 修改一开始设置的值后，那么就要重新计算balance的钱
        account.initBalance();
        this.check(account, account.getId());
        this.updateById(account);
    }

    @Override
    public void updateMoney(String userId) {
        List<Account> accountList = this.list(new BaseWrapper<Account>().init(userId));
        if (CollectionUtil.isEmpty(accountList)) {
            return;
        }
        List<String> accountIdList = accountList.stream().map(Account::getId).collect(Collectors.toList());
        List<Bill> billList = billService.list(new BaseWrapper<Bill>().init(userId).in("account_id", accountIdList));
        if (CollectionUtil.isEmpty(billList)) {
            return;
        }
        Map<String, List<Bill>> accountIdBillListMap = billList.stream().collect(Collectors.groupingBy(Bill::getAccountId));
        for (Account account : accountList) {
            List<Bill> bills = accountIdBillListMap.get(account.getId());
            if (CollectionUtil.isEmpty(bills)) {
                continue;
            }
            // 根据类型分组
            Map<String, BigDecimal> typeNumMap = bills.stream().collect(Collectors.toMap(Bill::getType, Bill::getMoney, BigDecimal::add));
            // 总数
            BigDecimal totalNum = BigDecimal.ZERO;
            if (CollectionUtil.isNotEmpty(typeNumMap)) {
                for (String type : typeNumMap.keySet()) {
                    if (Constants.BILL_TYPE_PAY.equals(type)) {
                        totalNum = totalNum.subtract(typeNumMap.get(type));
                    } else {
                        totalNum = totalNum.add(typeNumMap.get(type));
                    }
                }
            }
            account.setTotalNum(totalNum);
            account.initBalance();
        }
        this.updateBatchById(accountList);
    }

    private void check(Account account, String id) {
        AssertUtil.hasText(account.getName(), "名称不能为空");
        AssertUtil.hasText(account.getIcon(), "图标不能为空");
        AssertUtil.hasText(account.getMoney(), "金额不能为空");
        AssertUtil.hasText(account.getLastFourDigitsOfCard(), "尾号后四位不能为空");
        // 名称不能超过5个字符
        if (account.getName().length() > 7) {
            throw new BusinessException(ACCOUNT_NAME_FORMAT_ERROR.getErrorMsg());
        }
        // 检查名称，图标，尾号不同同时存在
        QueryWrapper<Account> qw = new QueryWrapper<>();
        qw.eq("name", account.getName()).eq("icon", account.getIcon())
                .eq("last_four_digits_of_card", account.getLastFourDigitsOfCard())
                .ne(StringUtils.isNotBlank(id), "id", id);
        List<Account> accountList = this.list(qw);
        if (CollectionUtil.isNotEmpty(accountList)) {
            throw new BusinessException("名称，图标，尾号不能同时重复");
        }
    }

}
